#include "ns3/core-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/network-module.h"
#include "ns3/applications-module.h"
#include "ns3/wifi-module.h"
#include "ns3/mobility-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/netanim-module.h"

#include <iostream>
#include <cstdint>

using namespace ns3;
NS_LOG_COMPONENT_DEFINE("starnet");

int main(){
	// set star network nodes
	uint32_t n=6;
	NodeContainer sta;
	sta.Create(n);
	NodeContainer ap;
	ap.Create(1);
	
	// set default channel and phy model
	YansWifiChannelHelper channel=YansWifiChannelHelper::Default();
	YansWifiPhyHelper phy=YansWifiPhyHelper::Default();
	phy.SetChannel(channel.Create());
	
	// AARF wifi
	WifiHelper wifi;
	wifi.SetRemoteStationManager("ns3::AarfWifiManager");
	
	// set mac type and SSID
	WifiMacHelper mac;
	Ssid ssid=Ssid("ns3-starnet-ssid");
	mac.SetType("ns3::StaWifiMac","Ssid",SsidValue(ssid),"ActiveProbing",BooleanValue(false));
	NetDeviceContainer sta_dev=wifi.Install(phy,mac,sta);
	mac.SetType("ns3::ApWifiMac","Ssid",SsidValue(ssid));
	NetDeviceContainer ap_dev=wifi.Install(phy,mac,ap);
	
	// set mobility model of sta
	MobilityHelper mobility;
	mobility.SetPositionAllocator(
		"ns3::GridPositionAllocator",
		"MinX",DoubleValue(0.0),
		"MinY",DoubleValue(0.0),
		"DeltaX",DoubleValue(5.0),
		"DeltaY",DoubleValue(10.0),
		"GridWidth",UintegerValue(3),
		"LayoutType",StringValue("RowFirst")
	);
	mobility.SetMobilityModel(
		"ns3::RandomWalk2dMobilityModel",
        	"Bounds",RectangleValue(Rectangle(-50,50,-50,50))
	);
	mobility.Install(sta);
	mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
	mobility.Install(ap);

	// TCP/IP
	InternetStackHelper stack;
	stack.Install(sta);
	stack.Install(ap);
	Ipv4AddressHelper addr;
	addr.SetBase("10.1.1.0","255.255.255.0");
	Ipv4InterfaceContainer interface=addr.Assign(sta_dev);
	addr.Assign(ap_dev);

	// UDP echo service
	UdpEchoServerHelper echo_server(9);
	ApplicationContainer server_apps=echo_server.Install(sta.Get(0));
	server_apps.Start(Seconds(1.0));
	server_apps.Stop(Seconds(10.0));

	UdpEchoClientHelper echo_client(interface.GetAddress(0),9);
	echo_client.SetAttribute("MaxPackets",UintegerValue(5000));
	echo_client.SetAttribute("Interval",TimeValue(Seconds(0.5)));
	echo_client.SetAttribute("PacketSize",UintegerValue(1024));
	ApplicationContainer client_apps=echo_client.Install(sta.Get(n-1));
	client_apps.Start(Seconds(2.0));
	client_apps.Stop(Seconds(10.0));

	Ipv4GlobalRoutingHelper::PopulateRoutingTables();
	Simulator::Stop(Seconds(10.0));
	
	// generate xml and trace data
	phy.EnablePcap("star",ap_dev.Get(0));
	AnimationInterface anim("starnet.xml");
	AsciiTraceHelper asciitracer;
	phy.EnableAsciiAll(asciitracer.CreateFileStream("starnet.tr"));

	Simulator::Run();
	Simulator::Destroy();
	return 0;
}
